#include <deque>
#include <iostream>
#include "ndt_scan_scene.h"
#include "ruler_manager.h"
#include "props.h"
#include "data.h"

namespace eintik::presentation::viewcore
{

    NdtScanSceneImpl::NdtScanSceneImpl(QObject *parent)
        : NdtScanScene(parent)
    {
    }

    void NdtScanSceneImpl::drawBackground(QPainter *painter, const QRectF &rect)
    {
        if (!sceneVisible())
        {
            return;
        }

        if (scan_type < 0)
        {
            return;
        }
        if (0 == scan_type)
        {
            draw_ascan(painter, rect);
        }
        else if (1 == scan_type)
        {
            draw_sscan(painter, rect);
        }
        else if (2 == scan_type)
        {
            draw_cscan(painter, rect);
        }
        else if (3 == scan_type)
        {
            draw_dscan(painter, rect);
        }
        else
        {
            // do nothing
        }
    }

    void NdtScanSceneImpl::draw_ascan(QPainter *painter, const QRectF &rect)
    {
        auto cnt_beam = property::cnt_beam();
        int beam = property::beam_location();
        if (beam > cnt_beam || beam < 0) {
            return;
        }
        auto vd = data::scan::ascan(id_scan)->frame_a_abs(beam);
        if (vd.empty())
        {
            return;
        }
        if (hightLight)
        {
            painter->fillRect(rect, QBrush(QColor(0x30, 0x30, 0x30)));
        }
        else
        {
            painter->fillRect(rect, QBrush(QColor(0x10, 0x10, 0x10)));
        }
        qreal x0 = rect.left();
        qreal w = rect.width();
        qreal y0 = rect.top();
        qreal h = rect.height();
        QVector<QPointF> aScanPointArray;
        auto x1 = vd.front().x;
        auto x2 = vd.back().x;
        for (int i = 0; i < vd.size(); ++i)
        {
            auto x = (vd[i].x - x1) / (x2 - x1) * w;
            auto y = h - vd[i].y * h;
            aScanPointArray.push_back(QPointF(x + x0, y + y0));
        }
        QPen x(QColor(0xff, 0xff, 0x0));
        painter->setPen(x);
        painter->drawPolyline(aScanPointArray.data(), aScanPointArray.size());

        #if 0
        *** 0917
        auto id_gate_start = eintik::property::pos_gate_start(0);
        auto id_gate_end = eintik::property::pos_gate_end(0);
        #endif

        auto d_raw = data::scan::ascan(id_scan)->frame_a_raw(beam);

        int id_gate_start, id_gate_end;
        if (eintik::property::pos_gate_isync(0, d_raw.data(), d_raw.size(), id_gate_start, id_gate_end))
        {
            double physical_x_start = vd[id_gate_start].x;
            double physical_x_end = vd[id_gate_end].x;
            qreal pixel_x_start = (physical_x_start - x1) / (x2 - x1) * w + x0;
            qreal pixel_x_end = (physical_x_end - x1) / (x2 - x1) * w + x0;
            qreal gate_y = y0 + h * 0.25;

            QPen gatePen(QColor(0xff, 0x00, 0x00)); // 红色
            gatePen.setWidth(2);
            painter->setPen(gatePen);
            painter->drawLine(QPointF(pixel_x_start, gate_y), QPointF(pixel_x_end, gate_y));
            painter->setPen(Qt::white);
            painter->drawText(QPointF(pixel_x_start, gate_y - 10), "A");
        }

        // Gate (1)
        #if 0
        *** 0917
        auto id_gate_start_1 = eintik::property::pos_gate_start(1);
        auto id_gate_end_1 = eintik::property::pos_gate_end(1);
        #endif

        int id_gate_i = -1;
        if (eintik::property::pos_gate_isync(1, d_raw.data(), d_raw.size(), id_gate_start, id_gate_end, &id_gate_i))
        {
            double physical_x_start_1 = vd[id_gate_start].x;
            double physical_x_end_1 = vd[id_gate_end].x;
            qreal pixel_x_start_1 = (physical_x_start_1 - x1) / (x2 - x1) * w + x0;
            qreal pixel_x_end_1 = (physical_x_end_1 - x1) / (x2 - x1) * w + x0;
            qreal gate_y_1 = y0 + h * 0.75;

            QPen gatePen1(QColor(0x00, 0xff, 0x00));
            gatePen1.setWidth(2);
            painter->setPen(gatePen1);
            painter->drawLine(QPointF(pixel_x_start_1, gate_y_1), QPointF(pixel_x_end_1, gate_y_1));
            painter->drawText(QPointF(pixel_x_start_1, gate_y_1 - 10), "B");
        }

        if (-1 != id_gate_i)
        {
            auto ratio_i = property::threadhold_gate_i();
            auto gate_y_1 = y0 + (h - h * ratio_i);

            auto cnt = d_raw.size();
            auto pixel_x = id_gate_i * w / cnt + x0;
            auto w_gate_i = w / 20;
            
            QPen gatePen1(QColor(0x00, 0xff, 0xff));
            gatePen1.setWidth(2);
            painter->setPen(gatePen1);
            painter->drawLine(QPointF(pixel_x - w_gate_i / 2, gate_y_1), QPointF(pixel_x + w_gate_i / 2, gate_y_1));
            painter->drawText(QPointF(pixel_x - w_gate_i / 2, gate_y_1 - 10), "I");
        }

        //item
        double minPhysical = 0.0;
        auto maxPhysical = eintik::property::signal_range();
        View->getRulerManager()->setRulerRange(Bottom_Ruler, minPhysical, maxPhysical, "mm");
        View->getRulerManager()->setRulerRange(Left_Ruler, 100, 0, "%");
    }
    void NdtScanSceneImpl::draw_sscan(QPainter *painter, const QRectF &rect)
    {
        auto vd = data::scan::sscan(id_scan)->frame_b_transpose();
        if (vd.empty())
        {
            return;
        }
        auto w = property::cnt_beam();
        auto h = property::cnt_points();
        QImage image(vd.data(), w, h, QImage::Format_Indexed8);
        image.setColorTable(colorTable);
        painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
        painter->drawImage(rect, image, QRectF(QPointF(0, 0), image.size()), Qt::OrderedDither);

        int id_beam = property::beam_location();
        double x = rect.width() * 1.0 / (w - 1) * id_beam;
        // painter->save();
        QPen pen(Qt::red, 3);
        painter->setPen(pen);
        painter->drawLine(
            QPointF(rect.left() + x, rect.top()),
            QPointF(rect.left() + x, rect.bottom())
            );
        // painter->restore();

        View->getRulerManager()->setRulerRange(
            Bottom_Ruler,
            0,
            eintik::property::gap_range(),
            "mm");
        View->getRulerManager()->setRulerRange(
            Left_Ruler,
            0,
            eintik::property::signal_range(),
            "");
    }
    void NdtScanSceneImpl::draw_cscan(QPainter *painter, const QRectF &rect)
    {
        auto w1 = static_cast<int>(rect.width());
        if (w1 <= 0)
        {
            return;
        }
        auto w2 = (w1 + 3) & ~3;
        auto vd = data::scan::cscan(id_scan)->frame_c(w1, w2 - w1);
        // std::cout << "cscan id: " << id_scan << std::endl;
        if (vd.empty())
        {
            return;
        }
        auto h = vd.size() / w1;
        QImage image(vd.data(), w2, h, QImage::Format_Indexed8);
        image.setColorTable(colorTable);
        painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
        painter->drawImage(rect, image, QRectF(QPointF(0, 0), image.size()), Qt::OrderedDither);

        int id_beam = property::beam_location();
        auto w = property::cnt_beam();
        double y = rect.height() * 1.0 / (w - 1) * id_beam;

        // painter->save();

        QPen pen(Qt::red, 3);
        painter->setPen(pen);
        painter->drawLine(
            QPointF(rect.left()     ,rect.top() + y),
            QPointF(rect.left() + w1,rect.top() + y)
            );

	#if 0
        painter->drawLine(
            QPointF(50 , rect.top()),
            QPointF(50 , rect.bottom())
            );
        painter->restore();
	#endif

        auto a = data::scan::cscan(id_scan)->range();
        auto interval = eintik::property::cscan_interval();
        #if 0
        *** 0916
        View->getRulerManager()->setRulerRange(Bottom_Ruler, a.first, a.first + interval, "mm");
        #endif
        View->getRulerManager()->setRulerRange(Bottom_Ruler, a.first, a.first + interval, "ms");
        View->getRulerManager()->setRulerRange(Left_Ruler, 0, h, "");
    }
    void NdtScanSceneImpl::draw_dscan(QPainter *painter, const QRectF &rect)
    {
        auto w1 = static_cast<int>(rect.width());
        if (w1 <= 0)
        {
            return;
        }
        auto w2 = (w1 + 3) & ~3;
        auto vd = data::scan::dscan(id_scan)->frame_d(w1, w2 - w1);
        if (vd.empty())
        {
            return;
        }
        auto h = vd.size() / w1;
        QImage image(vd.data(), w2, h, QImage::Format_Indexed8);
        image.setColorTable(colorTable);
        painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
        painter->drawImage(rect, image, QRectF(QPointF(0, 0), image.size()), Qt::OrderedDither);

        auto a = data::scan::dscan(id_scan)->range();
        auto interval = eintik::property::cscan_interval();
        View->getRulerManager()->setRulerRange(Bottom_Ruler, a.first, a.first + interval, "mm");
        View->getRulerManager()->setRulerRange(Left_Ruler, 0, h, "cnt");
    }
}
